#include "dataform.h"
#include "ui_dataform.h"
#include "qdebug.h"
#include "pupil.h"
#include "resultform.h"
#include "mainwindow.h"

#include <QDoubleSpinBox>

void DataForm::quickSort( Pupil** students, int l, int r, int subjectIndex)
{
    Pupil* pupilLeft;
    Pupil* pupilRight;
    Pupil* middleElement;

    int right = r;
    int left = l;

    pupilLeft = students[left];
    pupilRight = students[right];
    middleElement = students[( left + right ) / 2];

    do {
        while(pupilLeft->getBall(subjectIndex) < middleElement->getBall(subjectIndex))
        {
            left++;
            pupilLeft = students[left];
        }
        while(pupilRight->getBall(subjectIndex) > middleElement->getBall(subjectIndex))
        {
            right--;
            pupilRight = students[right];
        }
        if (left <= right)
        {
            students[left] = pupilRight;
            students[right] = pupilLeft;
            left++;
            pupilLeft = students[left];
            right--;
            pupilRight = students[right];
        }
    } while (left <= right);

    if (left < r) quickSort(students, left, r, subjectIndex);
    if (right > l) quickSort(students, l, right, subjectIndex);
}

void DataForm::quickSortRating( Pupil** students, int l, int r)
{
    Pupil* pupilLeft;
    Pupil* pupilRight;
    Pupil* middleElement;

    int right = r;
    int left = l;

    pupilLeft = students[left];
    pupilRight = students[right];
    middleElement = students[( left + right ) / 2];

    do {
        while(pupilLeft->getRatingBall() < middleElement->getRatingBall())
        {
            left++;
            pupilLeft = students[left];
        }
        while(pupilRight->getRatingBall() > middleElement->getRatingBall())
        {
            right--;
            pupilRight = students[right];
        }
        if (left <= right)
        {
            students[left] = pupilRight;
            students[right] = pupilLeft;
            left++;
            pupilLeft = students[left];
            right--;
            pupilRight = students[right];
        }
    } while (left <= right);

    if (left < r) quickSortRating(students, left, r);
    if (right > l) quickSortRating(students, l, right);
}

void DataForm::calcGroupBonus(QList<Pupil*>& group, double summ, int subjectIndex, int place)
{
    double groupBonus = summ / group.size();
    QListIterator<Pupil*> groupIterator(group);
    while (groupIterator.hasNext())
    {
        Pupil* pupilInGroup = groupIterator.next();
        pupilInGroup->setBonus(subjectIndex, groupBonus);
        pupilInGroup->setSubjectPlace(subjectIndex, place);
    }
    group.clear();
}

DataForm::DataForm(QWidget *parent, QString title, QStringList subjectsList, int objectCount) :
    QWidget(parent),
    ui(new Ui::DataForm)
{
    ui->setupUi(this);

    int subjectCount = subjectsList.size();

    subjectsList.push_front(tr("Name"));
    this->subjectsList = subjectsList;

    setWindowTitle(title);
    ui->tableWidget->setColumnCount(subjectsList.count());
    ui->tableWidget->setRowCount(objectCount);
    ui->tableWidget->setHorizontalHeaderLabels(subjectsList);

    for (int i = 0; i < subjectCount; i++) {
        for (int j = 0; j < objectCount; j++) {
            QDoubleSpinBox * spinbox = new QDoubleSpinBox(this);
            spinbox->setRange(0, 20000);
            spinbox->setDecimals(2);
            spinbox->setValue(0.0);
            spinbox->setButtonSymbols(QDoubleSpinBox::NoButtons);

            ui->tableWidget->setCellWidget(j, i + 1, spinbox);
        }
    }
}

DataForm::~DataForm()
{
    delete ui;
}

void DataForm::on_pushButton_clicked()
{
    int studentsCount = ui->tableWidget->rowCount();

    int subjectCount = ui->tableWidget->columnCount() - 1;

    Pupil** students = new Pupil*[studentsCount];
    QString name;
    int ball;
    for (int i = 0; i < studentsCount; i++)
    {
        name = ui->tableWidget->item(i, 0)->text();

        Pupil* pupil = new Pupil(name, subjectCount);
        for (int j = 0; j < subjectCount; j++)
        {
            ball = ((QDoubleSpinBox*)ui->tableWidget->cellWidget(i, j + 1))->value();
            pupil->setBall(j, ball);
        }
        students[i] = pupil;
    }

    for (int j = 0; j < subjectCount; j++)
    {
        // Sort

        quickSort(students, 0, studentsCount - 1, j);

        // Set bonuses here
        int currentBall = students[studentsCount - 1]->getBall(j);
        QList<Pupil*> group;
        int bonus = studentsCount;
        double summ = 0;
        int place = 1;

        for (int i = studentsCount - 1; i >= 0; i--, bonus--)
        {
            Pupil* pupil = students[i];
            if (pupil->getBall(j) != currentBall)
            {
                calcGroupBonus(group, summ, j, place);
                group.append(pupil);
                currentBall = pupil->getBall(j);
                summ = bonus;
                place++;
            }
            else
            {
                group.append(pupil);
                summ += bonus;
            }
        }

        if (group.size() > 0)
            calcGroupBonus(group, summ, j, place);
    }

    for (int i = 0; i < studentsCount; i++)
    {
        double sum = 0;
        Pupil* pupil = students[i];
        for (int j = 0; j < subjectCount; j++)
        {
            sum += pupil->getBonus(j);
        }
        pupil->setRatingBall(sum);
        students[i] = pupil;
    }

    // Sort Rating

    quickSortRating(students, 0, studentsCount - 1);

    // Set Rating Places

    int j = 1;
    Pupil* firstpupil = students[studentsCount - 1];
    firstpupil->setRatingPlace(j);
    students[studentsCount] = firstpupil;
    for (int i = studentsCount - 1; i>= 0; i--)
    {
        Pupil* firstPupil = students[i + 1];
        Pupil* secondPupil = students[i];
        if (firstPupil->getRatingBall() <= secondPupil->getRatingBall())
        {
            secondPupil->setRatingPlace(j);
            students[i] = secondPupil;
        }
        if (firstPupil->getRatingBall() > secondPupil->getRatingBall())
        {
            j++;
            secondPupil->setRatingPlace(j);
            students[i] = secondPupil;
        }
    }

    // Output

    for(int i = studentsCount - 1; i >= 0; i--)
    {
        Pupil* pupil = students[i];
        qDebug() << endl << pupil->getName() << " ";

        for (int j = 0; j < subjectCount; j++)
        {
            qDebug() << pupil->getBall(j) << " "
                     << pupil->getBonus(j)
                     << " " << pupil->getSubjectPlace(j);
        }
        qDebug() << endl << pupil->getRatingBall() << " " << pupil->getRatingPlace();
    }
    QString title = windowTitle();

    emit openResultForm(students, studentsCount, title, subjectsList);
}
